package sound;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.LineUnavailableException;
import java.util.Properties;

/**
 * Audio tone generator, using the Java sampled sound API.
 *
 * @author andrew Thompson
 * @version 2007/12/6
 */
public class Sound {

    static AudioFormat af;
    static SourceDataLine sdl;
    boolean file = true;
    boolean web = false;
    static boolean tagged = false;
    static String fileText = "";  // file located in this folder
    static String urlText = "";
    static boolean sp = false;
    static boolean error = false;
    static beep b;
    static Integer wordsPerMinute = 12;
    static int dot = 60, dash = 180, space = 60;
    static String newsReadUrl = "";
    static String newsReadFile = "";
    static StringBuilder sbLine = new StringBuilder("");
    static String ident =  "";

    public Sound() {
    }

    /**
     * Generates a tone.
     *
     * @param hz Base frequency (neglecting harmonic) of the tone in cycles per
     * second
     * @param msecs The number of milliseconds to play the tone.
     * @param volume Volume, form 0 (mute) to 100 (max).
     * @param addHarmonic Whether to add an harmonic, one octave up.
     */
    public static void main(String[] args) {
        say("Sound started");


        getProperties();

        if (newsReadUrl.equals("")) {
            say("News read url is blank.");
            if (newsReadFile.equals("")) {
                String err = "News read file is also blank.  Ending program.";
                say(err);
                sbLine = new StringBuilder(err); // plays the err line
            } else {
                say("News read file is " + newsReadFile);
                readSourceFile();
            }
        } else {
            say("News read url is " + newsReadUrl);
            readSourceUrl();
        }
        playStringBuilderLine();
    }

    /**
     * plays the string builder line, and filters out tags
     */
    private static void playStringBuilderLine() {
        try {
            //b = new beep(800, 200, 20, false);
            StringBuilder id = new StringBuilder(" QST DE W3TTT TRANSMISSION FOR CODE PRACTICE AND BEACON ");
            id = new StringBuilder(ident);
            b = new beep();
            b.open();
            b.setDot(dot);  // from properties file
            b.setDash(dash);
            b.setSp(dash);

            // send a -...- BT break char
            b.play(dash);
            b.quiet(space);
            b.play(dot);
            b.quiet(space);
            b.play(dot);
            b.quiet(space);
            b.play(dot);
            b.quiet(space);
            b.play(dash);

            // remove the bad tags
            removeTags(sbLine);

            int totprev = -1;
            int tot = 0;
            int cycle = wordsPerMinute * 5 * 10; // 5 char/word and 10 min/cycle

            // display it and/or play it
            int played = 0;
            for (int i = 0; i < sbLine.length(); i++) {


                char c = sbLine.charAt(i);
                if (c == '<') {   // filter out any tags leaving only content
                    tagged = true;
                }
                if (c == '>') {
                    tagged = false;
                }
                if (!tagged && c != '>') {
                    //say(c);
                    
                    tot = played++ / cycle;
                    if (tot != totprev) {
                        say(" time for ident : its " + played + " " + tot);
                        for (int j = 0; j < id.length(); j++){
                            b.playLetter(id.charAt(j));
                        }
                    }
                    totprev = tot;

                    b.playLetter(c);
                }
            }
        } catch (Exception e) {
            System.out.println("caught e " + e.getLocalizedMessage());
        } finally {
            b.close();
        }
    }

    /**
     * reads the source file and copies the text to the string builder line
     */
    private static void readSourceFile() {
        FlatFile ff = new FlatFile();
        if (ff.open(newsReadFile)) {
            while (!ff.eof) {
                String line = ff.next();
                sbLine.append(line);      // appending the line to the string builder
            }
            ff.close();
        } else {
            say("file not found");
        }
    }

    /**
     * reads the source URL and copies the text to the string builder line
     */
    private static void readSourceUrl() {
        ReadURL ru = new ReadURL();
        ru.setNewsFeedUrl(newsReadUrl);
        ru.readNewsFeed();
        //say(ru.getNewsFeedUrl());
        sbLine = ru.getSbNewsFeed();
    }

    private static void removeTags(StringBuilder sb) {
        //sb.delete(5002, 999999);
        removeStrAll(sb, "&#39;");
        removeStrAll(sb, "&nbsp;");
        removeStrAll(sb, "&raquo;");
        removeStrAll(sb, "Google");
        removeStrAll(sb, "&amp;");
        removeStrAllBetween(sb, "<style", "</style>");
        removeStrAllBetween(sb, "<script", "</script>");
        removeStrAllBetween(sb, "<select", "</select>");
        removeStrAllBetween(sb, "<form", "</form>");
        //removeStrAllBetween(sb, "<div", "/div");
        //   removeStrAll(sb, "   ");
        //removeSpaces(sb);


    }

    private static void removeSpaces(StringBuilder sb) {
        int len = sb.length();
        //say("len is " + len);
        int cnt = 0;
        int i2 = 0;
        for (int i = 0; i < 3652; i++) {
            //say("char at "+ i +" is " + sb.charAt(i) );
            if (sb.charAt(i) == ' ') {
                cnt = cnt + 1;
                while (sb.charAt(i + 1) == ' ') {
                    sb.deleteCharAt(i + 1);
                    // say('z');
                }
            }
            i2 = i;
        }
        //say("i ended at " + i2);
        //say("found spaces = " + cnt);
    }

    private static void removeStrAll(StringBuilder sb, String s) {
        while (sb.indexOf(s) > 0) {
            int beg = sb.indexOf(s);
            int end = beg + s.length();
            sb.delete(beg, end);
        }
    }

    private static void removeStrAllBetween(StringBuilder sb, String s1, String s2) {
        while (sb.indexOf(s1) > 0) {
            int beg = sb.indexOf(s1);
            int end = sb.indexOf(s2) + s2.length();
            sb.delete(beg, end);
        }
    }

    private static void getProperties() {

// Get program config.properties
        Properties prop = new Properties();
        InputStream input = null;
        try {
            input = new FileInputStream("./config.properties");
            prop.load(input);
        } catch (Exception e) {
            say("" + e);
            error = true;
        } finally {
            //say("finally, properties opened");
        }

        if (error == false) {
            try {
                // get parameters from config.properties file
                String tprop;

                tprop = prop.getProperty("WordsPerMinute");
                if (null != tprop) {
                    wordsPerMinute = Integer.valueOf(tprop);
                    say("Running at " + wordsPerMinute + " words per minute.");
                    dot = 720 / wordsPerMinute;
                    space = dot;
                    dash = dot * 3;
                }

                tprop = prop.getProperty("newsReadUrl");
                if (null != tprop) {
                    newsReadUrl = tprop;
                }


                tprop = prop.getProperty("newsReadFile");
                if (null != tprop) {
                    newsReadFile = tprop;
                }

                tprop = prop.getProperty("ident");
                if (null != tprop) {
                    ident = tprop;
                }


            } catch (Exception e) {
                say("" + e);
                error = true;
                //strError = "Can not read properties";
            } finally {
                //say("finally, properties read");
            }
        }
    }

    private static void say(String s) {
        System.out.println(s);
    }

    private static void say(char c) {
        System.out.print(c);
    }

    private static void say(StringBuilder sb) {
        System.out.print(sb);
    }
}